<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>手写new</title>
</head>
<body>
    <script>
        function Person(name,age) {
            this.name = name
            this.age = age

            // return {} 
            return 1
        }

        Person.prototype.do = function () {
            console.log("学习 React");
        }

        //手写new
        
        function myNew(constr,...args) {
            //创建一个对象
            const obj = {}
            //调用构造函数并使构造函数的this指向实例对象
            //rest参数返回一个实参数组,所以不用call,用apply
            //apply做了三件事: 调用其前面的函数,改变this指向,返回构造函数的返回值
            const re = constr.apply(obj,args)

            //把实例对象的隐式原型指向构造函数的显示原型,则实例对象中的constructor指向的是构造函数
            obj.__proto__ = constr.prototype

            //判断返回值
            if(typeof re === "object" && re !== "null" || typeof re === "function"){
                return re
            } else {
                return obj
            }

        }

        //传两个参,参数1是构造函数,其他参数是构造函数的传参,返回值应是实例化对象
        const p1 = myNew(Person, "张三", "20")
        const p2 = new Person("李四","18")
        //如果构造函数的返回值是基本数据类型,p1接收实例化对象,否则p1接收构造函数返回的引用数据类型
        console.log("p1",p1);
        console.log("p2",p2);

    </script>
</body>
</html>